function []=lpccodec_v6(plik_in,plik_out)
% Koder LPC, Kwant 1999
%
% Sposób u¿ycia:
% 	lpccodec('plik_wejœciowy.wav', 'plik_wyjœciowy.wav');
%
%	Wymagana wersja matlab: 5.x
%
% lpcCodec.m




% ====================  koder  =====================      

% czytanie pliku  wejœciowego
	[x]= wavread( plik_in );
	Fs= 8000;

% obliczanie d³ugoœci pliku
	eof= length(x);

% lpc nieprawid³owo dzia³a na zerowych próbkach wiêc niedopuszczam do tego
	for l=1:eof
  	if( x(l)==0 )
    	x(l)=eps;
		end
	end

% Filtrowanie sygnalu wejsciowego filtrem BP 10-900Hz
% ograniczenie pasma dla sygna³u z którego bêdzie obliczany pitch
	Impulse= fir1( 128, [50/(Fs/2) 900/(Fs/2)], 'high' );
	PitchX_orig= filter(Impulse, 1, [x; zeros(128,1)] );
	PitchX= PitchX_orig( 65:eof+64 );

% preemfaza uwypuklenie wysokich czêstotliowœci
	x(2:eof)=x(2:eof)-0.9375*x(1:eof-1);

% potrzebne do autokorelacji
	n=1:240;                              
	index=1;
	maximum=zeros(1,240);

%	wstêpne przeliczone wartoœci
%	okno Hamminga
	h= Hamming( 240 );

%	g³ówna pêtla encodera
	for l=1:180:eof-240

	% 'we' sygna³ bie¿¹cej ramki
  	we=x(l:l+239).*h;
   
	%	kombinacje w celu poprawnego obliczenia wartoœci pitch, clipping
		PitchXnoWin=[PitchX(l:l+239)' zeros(1,240)];  
		Cl=0.7*min( max(PitchXnoWin(1:80)), max(PitchXnoWin(80:240)) );

	% clipping sygna³u (aby uwypukliæ czêstotliwoœæ g³ówn¹)
		for k=1:480
    	if PitchXnoWin(k)>= Cl
      	clipper(k)=PitchXnoWin(k)-Cl;
			elseif PitchXnoWin(k)<=-Cl
 				clipper(k)=PitchXnoWin(k)+Cl;
			else
				clipper(k)=0;
			end
		end
   
	%	Autokorelacja  
   auto=zeros(1,240);
   for K=0:239
      auto(K+1)=sum( clipper(n).*clipper(n+K) );
   end
   
	%	Maksima autokorelacji
   maximum_1=maximum;     %maksima z poprzedniej iteracji
   maximum(1)=0;
   for K=2:239
      if auto(K-1)<auto(K) & auto(K)>auto(K+1)
         if auto(K)>0
            maximum(K)=auto(K);
         else
            maximum(K)=0;
         end
      elseif auto(K-1)<auto(K) & auto(K)==auto(K+1) %maksimum p³askie
         z=K+1;
         while auto(K)==auto(z) & z<239
            z=z+1;
         end
         
         for y=K:z
            if auto(K)>auto(z)
               maximum(y)=auto(K);
            else
               maximum(y)=0;
            end
         end
         K=z;
      else
         maximum(K)=0;
      end
		end
   
		[max1 imax1]=max(maximum_1);
		[max0 imax0]=max(maximum);
  
	%	Okreœlanie czy g³oska jest dŸwiêczna czy bezdŸwiêczna
	%	Jest to krytyczna faza kodera, od prawid³owej decyzji voiced/unvoiced zale¿y w znacznym stopniu jakoœæ generowanego dŸwiêku 
		if imax1+imax1*0.2>imax0 & imax1-imax1*0.2<imax0
			if max0>0.3*auto(1)
				Pitch=imax0;
      else
         Pitch=0;
      end
		else
      Pitch=0;
		end
   
%	To samo co wy¿ej tylko w mniej wyrafinowany sposób.
%
%	if max0 > 0.3*auto(1)
%		Pitch= imax0;
%	else
%		Pitch= 0;
%	end

	%	LPC wykorzystujê funkcjê LPC z Matlaba
		[A G]=lpc(we,10);
	
	%	Sk³adanie danych wyjœciowych 
		Coeff(index,1:11)=A;		% parametry LPC
		Coeff(index,12)=G;			%	wzmocnienie
		Coeff(index,13)=Pitch;	% Pitch (jeœli Pitch=0 to g³oska jest bezdŸwiêczna), w przeciwnym wypadku pitch jest odleg³oœci¹ pomiêdzy kolejnymi impulsami pobudzenia (w samplach Fs= 8000Hz)
   
	%
		if index>=2 & Coeff(index,13)>0 & Coeff(index-1,13)==0
			Coeff(index-1,13)=imax1;
		end
   
	%	numer kolejnej ramki
		index=index+1
	end

%	likwidowanie pojedynczych szumow....
%	Jeœli kolejne trzy ramki s¹: V, UV, V to œrodkow¹ ustaw jako Voiced
%	Jeœli kolejne trzy ramki s¹: UV, V, UV to œrodkow¹ ustaw jako Unvoiced
	for l=1:index-3
		if Coeff(l,13)>0 & Coeff(l+1,13)==0 & Coeff(l+2,13)>0
       Coeff(l+1,13)=round((Coeff(l,13)+Coeff(l+2,13))/2);
    elseif Coeff(l,13)==0 & Coeff(l+1,13)>0 & Coeff(l+2,13)==0
       Coeff(l+1,13)=0;
    end
 end
 
% ================= Koniec Kodera ==================




%	Parametrami transferowymi jest tablica (macierz) Coeff(...,...) Opis wy¿ej.
% modyfikuj¹c t¹ tablicê (patrz ni¿ej) mo¿na uzyskaæ ciekawe efekty!

% Tylko szept
%	Coeff( :, 13 )= 0;

% Wszystko tym samym tonem (œrednim z ca³ej próbki)
%	Coeff( :, 13 )= round( mean( Coeff(:,13) ).*( Coeff(:,13)~=0 ) );

%	Wszystko tym samym tonem, tylko ni¿ej
%	Coeff( :, 13 )= round( mean( Coeff(:,13)*4 ).*( Coeff(:,13)~=0 ) );

% dwa razy ni¿sza czêstotliwoœæ podstawowa (Pitch = Pitch/2)
%	Coeff( :, 13 )= Coeff( :, 13 ).*2;

% dyskretne wartoœci Pitch
%	Coeff( :, 13 )= round( Coeff(:, 13)./16 ).*16;

% Wszystkie g³oski tak samo g³oœno
	Coeff( :, 12 )= mean( Coeff(:, 12) );




% ===================  Dekoder  ====================

	LastPitch=0;
	excit=zeros(1,index*180);
	count=1;
	Coeff(1,:)=Coeff(2,:);           %przepisanie pierwszej wartosci Coeff bo jest nieprawidlowa

%	generowanie CA£EGO pobudzenia
	for l=1:180:(index-1)*180
		if Coeff(count,13)==0                          %unvoiced
			r= randn( 1, 180 );
			r= r/max( abs(r) );
      excit(l:l+179)=(rand(1,180)*2-1);
      LastPitch=0;
		else                                           %voiced
      for x= l+Coeff(count,13)-LastPitch:Coeff(count,13):l+179
				excit(x)= 1;
      end
      LastPitch=l+179-x;
		end
		count=count+1;
	end   

% g³oœnoœæ:
	sin2=sin((1:360)*pi/360).*sin((1:360)*pi/360);
	for l=1:index-2
  	for x=1:180
    	excit(l*180+x-90)=excit(l*180+x-90) * (Coeff(l,12)*sin2(x+180)+Coeff(l+1,12)*sin2(x));
		end
	end

%	filtr LPC
	Coeff(:,2:11)=- Coeff(:,2:11);

	for l=11:(index-1)*180 
  	 excit(l)=sum(excit(l:-1:l-10).*Coeff( ceil(l/180) ,1:11));
	end

%	deemfaza
	excit(2:(index-1)*180)=excit(2:(index-1)*180)+0.9375*excit(1:(index-1)*180-1);

% normowanie sygna³u
	excit( length(excit)-180*3: length(excit) )= 0;
	excit( 1:180 )= 0;
	max_output=max(excit);
	min_output=-min(excit);
	out=excit/max([min_output,max_output]);

% zapis do pliku
	wavwrite(out,8000,16, plik_out );

